//
//  DKHTTPRequest.m
//  Sekiss
//
//  Created by Alex on 15-3-3.
//  Copyright (c) 2015年 Alex. All rights reserved.
//

#import "DKHTTPRequest.h"
#import "SVProgressHUD.h"

#define DBNAME      @"DKHTTPRequest.sqlite"
#define DBTABLE     @"DBTableName"
#define DBRURL      @"DBRequestUrl"
#define DBPARAM     @"DBParameter"
#define DBSDATA     @"DBServerData"

@interface DKHTTPRequest()
{
    sqlite3 *db;
}
@end





@implementation DKHTTPRequest

//-------------------------------------------------------------------------------------
#pragma mark- 基本操作
-(void)openDB
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documents = [paths objectAtIndex:0];
    NSString *database_path = [documents stringByAppendingPathComponent:DBNAME];
    
    if (sqlite3_open([database_path UTF8String], &db) != SQLITE_OK) {
        sqlite3_close(db);
        NSLog(@"数据库打开失败");
    }
}

-(void)closeDB
{
    sqlite3_close(db);
}

-(BOOL)execUpdate:(NSString *)sql
{
    char *err;
    if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) {
        // NSLog(sql);
        sqlite3_close(db);
        // NSLog([NSString stringWithFormat:@"sqlError:%s",err]);
        return NO;
    }
    return YES;
}

-(sqlite3_stmt *)execQuery:(NSString*)sql
{
    sqlite3_stmt * statement;
    if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) != SQLITE_OK) {
        //   NSLog(sql);
        sqlite3_close(db);
        return nil;
    }
    return statement;
}


//-------------------------------------------------------------------------------------
#pragma mark- 获取单例
+(instancetype)shareHTTPRequest
{
    static DKHTTPRequest *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
        [instance initDataBase];
    });
    return instance;
}


//-------------------------------------------------------------------------------------
#pragma mark- 初始化数据库
-(void)initDataBase
{
    @synchronized(self)
    {
        [self openDB];
        [self execUpdate:[NSString stringWithFormat:@"create table if not exists %@ (id integer primary key autoincrement,%@ blob,%@ varchar,%@ blob)",DBTABLE,DBRURL,DBPARAM,DBSDATA]];
        [self closeDB];
    }
}


//-------------------------------------------------------------------------------------
//数据库的api
#pragma mark- 数据库基本接口
//根据参数更新最新的返回结果
-(void)setResponseDataWithUrl:(NSString*)url Parameter:(NSData*)param ServerData:(NSData*)sData
{
    @synchronized(self)
    {
        if(sData==nil)
        {
            return;//若没有结果，则不存储
        }
        
        [self openDB];
        //--------------------------
        //查询是否存在该条记录
        NSString* sql=[NSString stringWithFormat:@"select %@ from %@ where %@='%@' and %@ = ? ",DBSDATA,DBTABLE,DBRURL,url,DBPARAM];
        sqlite3_stmt * statement;
        if( sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK )
        {
            sqlite3_bind_blob(statement, 1, [param bytes], (int)[param length], SQLITE_TRANSIENT);
            sqlite3_step(statement);
        }
        //--------------------------
        
        BOOL isUpdate=NO;
        if(statement!=nil)
        {
            if (sqlite3_step(statement) == SQLITE_ROW) {
               //存在该条记录，则更新
                isUpdate=YES;
                NSString* sqliteQuery=[NSString stringWithFormat:@"update %@ set %@=? where %@= ? and %@='%@'",DBTABLE,DBSDATA,DBPARAM,DBRURL,url];
                sqlite3_stmt* updateStatement;
                if( sqlite3_prepare_v2(db, [sqliteQuery UTF8String], -1, &updateStatement, NULL) == SQLITE_OK )
                {
                    sqlite3_bind_blob(updateStatement, 1, [sData bytes], (int)[sData length], SQLITE_TRANSIENT);
                    sqlite3_bind_blob(updateStatement, 2, [param bytes], (int)[param length], SQLITE_TRANSIENT);
                    sqlite3_step(updateStatement);
                }
                sqlite3_finalize(updateStatement);
            }
        }
        sqlite3_finalize(statement);
        
        if(isUpdate==NO)
        {//数据库不存在该条记录，则插入
            NSString* sqliteQuery=[NSString stringWithFormat:@"insert into %@ (%@,%@,%@) values ('%@',?,?)",DBTABLE,DBRURL,DBPARAM,DBSDATA,url];
            sqlite3_stmt* insertStatement;
            if( sqlite3_prepare_v2(db, [sqliteQuery UTF8String], -1, &insertStatement, NULL) == SQLITE_OK )
            {
                sqlite3_bind_blob(insertStatement, 1, [param bytes], (int)[param length], SQLITE_TRANSIENT);
                sqlite3_bind_blob(insertStatement, 2, [sData bytes], (int)[sData length], SQLITE_TRANSIENT);
                sqlite3_step(insertStatement);
            }
            sqlite3_finalize(insertStatement);
        }
        
        [self closeDB];
    }
}


//根据参数获取上次的返回结果，若不存在，则返回nil
-(NSData*)responseDataWithUrl:(NSString*)url Parameter:(NSData*)param
{
    @synchronized(self)
    {
        [self openDB];
        NSData* result=nil;
        //--------------------------
        //查询是否存在该条记录
        NSString* sql=[NSString stringWithFormat:@"select %@ from %@ where %@='%@' and %@ = ? ",DBSDATA,DBTABLE,DBRURL,url,DBPARAM];
        sqlite3_stmt * statement;
        if( sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, NULL) == SQLITE_OK )
        {
            sqlite3_bind_blob(statement, 1, [param bytes], (int)[param length], SQLITE_TRANSIENT);
            sqlite3_step(statement);
        }
        //--------------------------
        
        if(statement!=nil)
        {
            if (sqlite3_step(statement) == SQLITE_ROW) {
                //存在该条记录，则取出
                int length = sqlite3_column_bytes(statement, 0);
                result=[NSData dataWithBytes:sqlite3_column_blob(statement, 0) length:length];
            }
        }
        sqlite3_finalize(statement);
        
        [self closeDB];
        return result;
    }
}

// 新协议 头接口
+(void)sendNewDataWithShortUrl:(NSString*)url//协议名（服务器地址为serverUrl时调用）
                      Param:(NSString*)param//参数，为String型
                 ImageArray:(NSArray*)iArray
                    TimeOut:(CGFloat)tOut//超时时间
                 Completion:(BOOL (^)(NSMutableDictionary* serverDic,DKHTTPResponseType bufferType))completion//本次请求的数据(服务器数据,是否是本地缓存)
                IsBuffering:(BOOL)buffer//该条数据是否是需要缓存的
          IsNeedReplaceWrap:(BOOL)isWrap//是否需要替换/n
            IsUseUpLoadHead:(BOOL)isHead
{
    [DKHTTPRequest sendDataWithLongUrl:[NSString stringWithFormat:@"%@%@",NewServerUrl,url]
                                 Param:param
                            ImageArray:iArray
                               TimeOut:tOut
                            Completion:completion
                           IsBuffering:buffer
                     IsNeedReplaceWrap:isWrap
                       IsUseUpLoadHead:isHead];
}


//-------------------------------------------------------------------------------------
#pragma mark- 对外接口
+(void)sendDataWithShortUrl:(NSString*)url//协议名（服务器地址为serverUrl时调用）
                      Param:(NSString*)param//参数，为String型
                 ImageArray:(NSArray*)iArray
                    TimeOut:(CGFloat)tOut//超时时间
                 Completion:(BOOL (^)(NSMutableDictionary* serverDic,DKHTTPResponseType bufferType))completion//本次请求的数据(服务器数据,是否是本地缓存)
                   IsBuffering:(BOOL)buffer//该条数据是否是需要缓存的
            IsNeedReplaceWrap:(BOOL)isWrap//是否需要替换/n
              IsUseUpLoadHead:(BOOL)isHead
{
    [DKHTTPRequest sendDataWithLongUrl:[NSString stringWithFormat:@"%@%@",NewServerUrl,url]
                                 Param:param
                            ImageArray:iArray
                               TimeOut:tOut
                            Completion:completion
                           IsBuffering:buffer
                     IsNeedReplaceWrap:isWrap
                       IsUseUpLoadHead:isHead];
}


+(void)sendDataWithLongUrl:(NSString*)url//协议名（完整地址）
                     Param:(NSString*)param//参数，为String型
                ImageArray:(NSArray*)iArray
                   TimeOut:(CGFloat)tOut//超时时间
                Completion:(BOOL (^)(NSMutableDictionary* serverDic,DKHTTPResponseType bufferType))completion//本次请求的数据(服务器数据,是否是本地缓存)
               IsBuffering:(BOOL)buffer//该条数据是否是需要缓存的
         IsNeedReplaceWrap:(BOOL)isWrap
           IsUseUpLoadHead:(BOOL)isHead
{
    //-------------------------------
    //输出请求，方便调试
    NSLog(@"request=%@",param);
    
    
    BOOL isFirst=YES;
    //-------------------------------
    NSData* paramData=[DKHTTPRequest generateDataWithParam:param ImageArray:iArray];
    if(buffer)
    {//该协议需要缓存
        NSData* lastData=[[DKHTTPRequest shareHTTPRequest] responseDataWithUrl:url Parameter:paramData];
        if(lastData!=nil)
        {//存在缓存，则调用
            isFirst=NO;
            NSMutableDictionary* lastDic=[NSJSONSerialization JSONObjectWithData:lastData options:NSJSONReadingMutableContainers error:nil];
            completion(lastDic,DKHTTPResponseTypeLocalData);
        }
    }
    
    
    //-------------------------------------------------------------------------
    //网络连接
    if(iArray==nil)
    {//普通Post请求
        //进行utf8编码
        param=[param stringByAddingPercentEscapesUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF8)];
        NSData* content=[param dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
        
        
        // 初始化请求, 这里是变长的, 方便扩展
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
        // 设置
        [request setURL:[NSURL URLWithString:url]];
        [request setHTTPMethod:@"POST"];
        [request setTimeoutInterval:tOut];
        NSString *contentLength = [NSString stringWithFormat:@"%ld",(unsigned long)[content length]];
        [request setValue:contentLength forHTTPHeaderField:@"Content-Length"];
        [request setHTTPBody:content];
        
        dispatch_async(dispatch_queue_create("DKHTTPRequestThread", NULL), ^(void)
                       {
                           //发送请求
                           NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
                           dispatch_async(dispatch_get_main_queue(), ^(void)
                                          {
                                              if (data==nil) //没有请求到数据或者无网络
                                              {
                                                  completion(nil,isFirst==YES?DKHTTPResponseTypeServerDataAtFirst:DKHTTPResponseTypeServerData);
                                                  [SVProgressHUD showInfoWithStatus:NSLocalizedString(@"网络连接错误", nil)];
                                                  return;
                                              }
                                              //输出结果，方便调试
                                              NSString *response = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                                              NSLog(@"response=%@",response);
                                              
                                              
                                              NSData *useData;
                                              if (isWrap)  //留着对特殊情况处理
                                              {
                                                  useData = data;
                                              }
                                              else
                                              {
                                                  useData = data;
                                              }
                                              //处理返回的json值
                                              NSMutableDictionary *resultJSON=nil;
                                              if(useData!=nil)
                                              {
                                                  resultJSON=[NSJSONSerialization JSONObjectWithData:useData options:NSJSONReadingMutableContainers error:nil];
                                                  //去除nsnull和nil
                                                  resultJSON = [DKHTTPRequest processDictionaryIsNSNull:resultJSON];
                                              }
                                              
                                              if ([[resultJSON objectForKey:@"code"] intValue]!=200)
                                              {
                                                  if ([url isEqualToString:@"http://fhc2017.visionfix.me/msg_getmsginfo_2017_"]) //消息通知不提示
                                                  {
                                                      
                                                  }
                                                  else
                                                  {
                                                      [SVProgressHUD showInfoWithStatus:[resultJSON objectForKey:@"msg"]];
                                                  }
                                              }
                                              
                                              //调用代码块
                                              BOOL isUseful=completion(resultJSON,isFirst==YES?DKHTTPResponseTypeServerDataAtFirst:DKHTTPResponseTypeServerData);
                                              if(isUseful && buffer)
                                              {//该协议需要缓存且缓存的内容不为空，则存储该结果
                                                  [[DKHTTPRequest shareHTTPRequest] setResponseDataWithUrl:url
                                                                                                 Parameter:paramData
                                                                                                ServerData:data];
                                              }
                                          });
                       });
    }
    //-------------------------------
    else
    {//图片表单请求
        NSString *TWITTERFON_FORM_BOUNDARY = @"0xKhTmLbOuNdArY";
        //根据url初始化request
        NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]
                                                               cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                           timeoutInterval:tOut];
        //-------------------------------------
        //表单格式
        //分界线(表单开始)
        NSString *MPboundary=[[NSString alloc]initWithFormat:@"--%@",TWITTERFON_FORM_BOUNDARY];
        //结束符(表单结束)
        NSString *endMPboundary=[[NSString alloc]initWithFormat:@"%@--",MPboundary];
        //http body的字符串(表单中间)
        NSMutableString *body=[[NSMutableString alloc]init];
        
        //-------------------------------------
        //将字段添加到表单
        NSArray* splitArray=[param componentsSeparatedByString:@"&"];
        NSMutableArray* keys=[[NSMutableArray alloc] init];
        NSMutableArray* values=[[NSMutableArray alloc] init];
        for(int i=0;i<splitArray.count;i++)
        {
            NSString* thisStr=splitArray[i];
            if(thisStr.length==0)
                continue;
            
            NSArray* paramSplitArray=[thisStr componentsSeparatedByString:@"="];
            if(paramSplitArray.count==2)
            {
                [keys addObject:paramSplitArray[0]];
                [values addObject:paramSplitArray[1]];
            }
            else if(paramSplitArray.count==1)
            {
                [keys addObject:paramSplitArray[0]];
                [values addObject:@""];
            }
            else
            {
                NSLog(@"DKHTTPRequest:参数错误-%@",param);
                return;
            }
        }
        //在表单中生成字段
        for(int i=0;i<keys.count;i++)
        {
            //字段分界线
            [body appendFormat:@"%@\r\n",MPboundary];
            //键
            [body appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",keys[i]];
            //值
            [body appendFormat:@"%@\r\n",[values[i] stringByAddingPercentEscapesUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF8)]];
        }
        
        //-------------------------------------
        //将图片添加到表单
        //得到图片的data
        NSMutableData *imageData=[[NSMutableData alloc] init];
        [imageData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
        for(int i=0;i<iArray.count;i++)
        {
            NSData* data=UIImageJPEGRepresentation(iArray[i], 0.5);
            //添加分界线，换行
            NSMutableString *detailBody=[[NSMutableString alloc]init];
            [detailBody appendFormat:@"%@\r\n",MPboundary];
            if(iArray.count==1&&isHead)
            {
                [detailBody appendFormat:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"head_img\"; filename=\"head_img.jpg\"\r\n"]];
            }
            else
            {
                //声明pic字段
                [detailBody appendFormat:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"goods_img%d\"; filename=\"goods%d.jpg\"\r\n",i+1,i+1]];
            }
            
            //声明上传文件的格式
            [detailBody appendFormat:@"Content-Type: image/jpge,image/gif, image/jpeg, image/pjpeg, image/pjpeg\r\n\r\n"];

            
            [imageData appendData:[detailBody dataUsingEncoding:NSUTF8StringEncoding]];
            [imageData appendData:data];
            [imageData appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
        }
        
        //加入结束符
        NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
        [imageData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
        
        
        if(iArray.count==0)
        {
            //将body字符串转化为UTF8格式的二进制
            [imageData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
            NSString *end=[[NSString alloc]initWithFormat:@"\r\n%@",endMPboundary];
            //加入结束符
            [imageData appendData:[end dataUsingEncoding:NSUTF8StringEncoding]];
        }
        
        //设置HTTPHeader中Content-Type的值
        NSString *content=[[NSString alloc]initWithFormat:@"multipart/form-data; boundary=%@",TWITTERFON_FORM_BOUNDARY];
        //设置HTTPHeader
        [request setValue:content forHTTPHeaderField:@"Content-Type"];
        
        //设置Content-Length
        [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[imageData length]] forHTTPHeaderField:@"Content-Length"];
        //设置http body
        [request setHTTPBody:imageData];
        //http method
        [request setHTTPMethod:@"POST"];
        
        dispatch_async(dispatch_queue_create("DKHTTPRequestThread", NULL), ^(void)
                       {
                           //发送请求
                           NSData* resultData = [NSURLConnection sendSynchronousRequest:request
                                                                      returningResponse:nil
                                                                                  error:nil];
                           
                           dispatch_async(dispatch_get_main_queue(), ^(void)
                                          {
                                              //输出结果，方便调试
                                              NSString* result= [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
                                              NSLog(@"response=%@",result);
                                              
                                              //处理返回的json值
                                              NSMutableDictionary *resultJSON=nil;
                                              if(resultData!=nil)
                                              {
                                                  resultJSON=[NSJSONSerialization JSONObjectWithData:resultData options:NSJSONReadingMutableContainers error:nil];
                                                  //去除nsnull和nil
                                                  resultJSON = [DKHTTPRequest processDictionaryIsNSNull:resultJSON];
                                              }
                                              
                                              //调用代码块
                                              BOOL isUseful=completion(resultJSON,isFirst==YES?DKHTTPResponseTypeServerDataAtFirst:DKHTTPResponseTypeServerData);
                                              if(isUseful && buffer)
                                              {//该协议需要缓存且缓存的内容不为空，则存储该结果
                                                  [[DKHTTPRequest shareHTTPRequest] setResponseDataWithUrl:url
                                                                                                 Parameter:paramData
                                                                                                ServerData:resultData];
                                              }
                                          });
                       });
    }
}



//根据参数和图片生成发出的data(用于本地数据库比对)
+(NSData*)generateDataWithParam:(NSString*)param
                     ImageArray:(NSArray*)iArray
{
    if(iArray.count==0)
    {//没有图片的情况下
        return [param dataUsingEncoding:NSUTF8StringEncoding];
    }
    else
    {//有图片的状态
        NSMutableData* data=[[NSMutableData alloc] initWithData:[param dataUsingEncoding:NSUTF8StringEncoding]];
        for(int i=0;i<iArray.count;i++)
        {
            UIImage* imageTmep=iArray[i];
            if([imageTmep isKindOfClass:[UIImage class]])
            {
                [data appendData:UIImageJPEGRepresentation(imageTmep, 1.0f)];
            }
        }
        return data;
    }
}


//清空所有缓存
+(void)clearData
{
    @synchronized([DKHTTPRequest shareHTTPRequest])
    {
        [[DKHTTPRequest shareHTTPRequest] openDB];
        [[DKHTTPRequest shareHTTPRequest] execUpdate:[NSString stringWithFormat:@"drop table if exists %@",DBTABLE]];
        [[DKHTTPRequest shareHTTPRequest] closeDB];
    }
}


/**
 处理dictionary中的NSNull和<null>
 
 @param obj dictionary
 @return 去除NSNull和<null>后的dictionary
 */
+(id)processDictionaryIsNSNull:(id)obj
{
    const NSString *blank = @"";
    
    if ([obj isKindOfClass:[NSDictionary class]])
    {
        NSMutableDictionary *dt = [(NSMutableDictionary*)obj mutableCopy];
        for(NSString *key in [dt allKeys])
        {
            id object = [dt objectForKey:key];
            if([object isKindOfClass:[NSNull class]])
            {
                [dt setObject:blank forKey:key];
            }
            else if ([object isKindOfClass:[NSString class]])
            {
                NSString *strobj = (NSString*)object;
                if ([strobj isEqualToString:@"<null>"])
                {
                    [dt setObject:blank forKey:key];
                }
            }
            else if ([object isKindOfClass:[NSArray class]])
            {
                NSArray *da = (NSArray*)object;
                da = [self processDictionaryIsNSNull:da];
                [dt setObject:da forKey:key];
            }
            else if ([object isKindOfClass:[NSDictionary class]])
            {
                NSDictionary *ddc = (NSDictionary*)object;
                ddc = [self processDictionaryIsNSNull:object];
                [dt setObject:ddc forKey:key];
            }
        }
        return [dt copy];
    }
    else if ([obj isKindOfClass:[NSArray class]])
    {
        NSMutableArray *da = [(NSMutableArray*)obj mutableCopy];
        for (int i=0; i<[da count]; i++)
        {
            NSDictionary *dc = [obj objectAtIndex:i];
            dc = [self processDictionaryIsNSNull:dc];
            [da replaceObjectAtIndex:i withObject:dc];
        }
        return [da copy];
    }
    else
    {
        return obj;
    }
}


@end
